/** ***********************************************************************************
* @file         ble_task.c
* @brief        蓝牙数据管理基础任务
* @details      主要用来处理蓝牙底层数据接口
* @author       杨小珛
* @date         2021/03/16
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#include "ble_task.h"
#include "mon_task.h"
#include "power_task.h"
#include "log_task.h"
#include "com_lib.h"


#define BLE_RECV_NAME    "BLE_RECV_TASK"
GaozMutexHandle_t ble_send_data_mutex;        /*BLE数据发送互斥体*/
GaozQueueHandle_t ble_recv_data_queue;        /*定义网络发送数据消息队列*/
GaozMutexHandle_t ble_recv_data_mutex;        /*BLE数据发送互斥体*/
GaozSemaphoreHandle_t ble_recv_semaphore;     /*BLE连接状态信号量*/
volatile uint8_t ble_power_man_id;            /*电源管理ID*/
ble_drive_state_callback_t ble_drive_state_cb;
ble_connect_data_counter_t ble_connect_data_counter;    

static void ble_data_handle_task( void * pvParameters );
static void ble_drive_data_queue_create(void);
static uint32_t ble_drive_data_queue_get(ble_recv_data_t *ble_msg ,uint32_t time_out);
static void ble_drive_data_para_init(void);
static void ble_drive_data_semaphore_create(void);
static uint8_t ble_drive_data_semaphore_get( uint32_t time_out );
static uint16_t ble_drive_connect_state_get( void );
static uint16_t ble_drive_acl_handle_get( void );

static void ble_data_printf_data_fun( ble_data_mode_e mode , uint8_t *p_data , uint16_t d_len );

static uint32_t ble_task_into_run_mode(void);
static uint32_t ble_task_into_sleep_mode(void);
static uint32_t ble_task_into_stop_mode(void);

static uint32_t ble_task_open_drive(void);
static void ble_task_data_processing( uint32_t time_out );
static uint32_t ble_drive_task_state_cb( uint8_t state );
static void ble_drive_cfg_broadcast_time( uint32_t time_ms );

static gatt_chara_def_short_t wifi_mgr_chara = {{
	ATT_CHARA_PROP_READ | ATT_CHARA_PROP_WRITE,
	0,
	0,
	0x2a06&0xff,
	0x2a06>>8
}};

static gatt_chara_def_short_t wifi_mgr_chara1 = {{
	ATT_CHARA_PROP_READ | ATT_CHARA_PROP_NOTIFY,
	0,
	0,
	0x2a00&0xff,
	0x2a00>>8
}};

static gatt_chara_def_short_t wifi_mgr_chara2 = {{
	ATT_CHARA_PROP_READ | ATT_CHARA_PROP_WWP | ATT_CHARA_PROP_NOTIFY,
	0,
	0,
	0xffe1&0xff,
	0xffe1>>8
}};

#define WIFIMAR_VALUE_LEN   BLE_DATA_MAX_LEN
#define WIFIMAR_CCC_FLAG_LEN 200
#define BLE_DEVICE_NAME "GAOZ_BLE"
#define BLE_DEVICE_NAME_LEN     26

static uint8_t wifimgr_value[WIFIMAR_VALUE_LEN];
static uint8_t wifimgr_ccc_cfg[WIFIMAR_CCC_FLAG_LEN];
static uint8_t device_name[BLE_DEVICE_NAME_LEN];

static uint8_t test_service[2] = 
{
    0x1810&0xff, 
    0x1810 >> 8
};

static uint8_t add_service[2] = 
{
    0xffe0&0xff, 
    0xffe0 >> 8
};

static ble_connect_state_t ble_connect_st;           /*BLE底层连接的状态*/
static ble_gatt_connect_e ble_gatt_connect_st;  /*BLE管理任务维护的网络状态*/
static ble_power_state_e ble_power_st;            /*BLE管理任务维护的网络状态*/

uint8_t data_write_callback(void *param)
{
    ble_recv_data_t recv_buf;
	gatt_srv_write_notify_t *pAttr = (gatt_srv_write_notify_t *)param;
    gaoz_mutex_lock( ble_recv_data_mutex );
    if( pAttr->valueLen > UART_RX_BUF_SIZE ) /*内存边界判断*/
    {
        pAttr->valueLen = UART_RX_BUF_SIZE; 
    }
    ble_data_printf_data_fun( BLE_DATA_READ , ( uint8_t *)wifimgr_value , pAttr->valueLen );
    recv_buf.data = ( uint8_t *)gaoz_malloc_mem( pAttr->valueLen + 8 ); /*动态申请空间，空间位置处于FreeRtos总栈空间中*/
    if( recv_buf.data != NULL )
    {
        memcpy( ( uint8_t *)recv_buf.data , ( uint8_t *)wifimgr_value ,pAttr->valueLen  );
        recv_buf.len = pAttr->valueLen;
        if( gaoz_queue_put( ble_recv_data_queue, ( void * )&recv_buf , 10 ) < 0 )
        {
            gaoz_free_mem( (void *)recv_buf.data );
        }
    }
    gaoz_mutex_unlock( ble_recv_data_mutex );
	return 0;
}

uint8_t wifi_changed_cb(void *param)
{
	OSI_PRINTFI("[GAOZ_BLE][%s:%d] param = %p,wifimgr_value=%s", __FUNCTION__, __LINE__,param,wifimgr_value);
	return 0;
}

uint8_t wifimgr_value_write_cb(void *param)
{
    OSI_PRINTFI("[GAOZ_BLE][%s:%d] param = %p,wifimgr_value=%s", __FUNCTION__, __LINE__,param,wifimgr_value);
	return 0;
}

uint8_t wifimgr_value_read_cb(void *param)
{
    OSI_PRINTFI("[GAOZ_BLE][%s:%d] param = %p,wifimgr_value=%s,wifimgr_value:%s", __FUNCTION__, __LINE__,param,wifimgr_value,wifimgr_ccc_cfg);
	return 0;
}

gatt_element_t config_wifi_service[]={
{
		//creat service and fill UUID
	    sizeof(test_service),
	   	ATT_PM_READABLE,
	    {ATT_UUID_PRIMARY},
	    ATT_FMT_SHORT_UUID | ATT_FMT_GROUPED,
	    (void *)test_service,
	    NULL,
	    NULL
	},
	{
		//creat chara and fill permission
	    sizeof(wifi_mgr_chara),
		ATT_PM_READABLE,
	    {ATT_UUID_CHAR},
	    ATT_FMT_SHORT_UUID | ATT_FMT_FIXED_LENGTH,
	    (void *)&wifi_mgr_chara,
	    wifi_changed_cb,//cb
	    wifimgr_value_read_cb//read callback
	},
	{
	    sizeof(wifimgr_value),
		ATT_PM_READABLE | ATT_PM_WRITEABLE,
	    {0x2a06},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY | ATT_FMT_FIXED_LENGTH,
	    (void *)wifimgr_value,
	    data_write_callback,
	    NULL
	},
	{
		//des
	    sizeof(wifimgr_ccc_cfg),
	    ATT_PM_READABLE | ATT_PM_WRITEABLE,
	    {ATT_UUID_CLIENT},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY|ATT_FMT_FIXED_LENGTH,
	    (void *)wifimgr_ccc_cfg,
	    wifi_changed_cb,
	    NULL
	},
	{
	    sizeof(wifi_mgr_chara1),
		ATT_PM_READABLE,
	    {ATT_UUID_CHAR},
	    ATT_FMT_SHORT_UUID | ATT_FMT_FIXED_LENGTH,
	    (void *)&wifi_mgr_chara1,
	    NULL,
	    NULL
	},
	{
	    sizeof(device_name),
		ATT_PM_READABLE,
	    {0x2a00},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY | ATT_FMT_FIXED_LENGTH,
	    (void *)device_name,
	    NULL,
	    NULL
	},
	{
	    sizeof(wifimgr_ccc_cfg),
	    ATT_PM_READABLE | ATT_PM_WRITEABLE,
	    {ATT_UUID_CLIENT},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY|ATT_FMT_FIXED_LENGTH,
	    (void *)wifimgr_ccc_cfg,
	    wifi_changed_cb,
	    NULL
	},
	{
		//creat service and fill UUID
	    sizeof(add_service),
	   	ATT_PM_READABLE,
	    {ATT_UUID_PRIMARY},
	    ATT_FMT_SHORT_UUID | ATT_FMT_GROUPED,
	    (void *)add_service,
	    NULL,
	    NULL
	},
	{
		//creat chara and fill permission
	    sizeof(wifi_mgr_chara2),
		ATT_PM_READABLE,
	    {ATT_UUID_CHAR},
	    ATT_FMT_SHORT_UUID | ATT_FMT_FIXED_LENGTH,
	    (void *)&wifi_mgr_chara2,
	    wifi_changed_cb,//cb
	    wifimgr_value_read_cb//read callback
	},
	{
		//fill chara value 
	    sizeof(wifimgr_value),
		ATT_PM_READABLE | ATT_PM_WRITEABLE,
	    {0x2906},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY | ATT_FMT_FIXED_LENGTH,
	    (void *)wifimgr_value,
	    data_write_callback,
	    NULL
	},
	{
		//des
	    sizeof(wifimgr_ccc_cfg),
	    ATT_PM_READABLE | ATT_PM_WRITEABLE,
	    {ATT_UUID_CLIENT},
	    ATT_FMT_SHORT_UUID | ATT_FMT_WRITE_NOTIFY|ATT_FMT_FIXED_LENGTH,
	    (void *)wifimgr_ccc_cfg,
	    wifi_changed_cb,
	    NULL
	},
};


/** ****************************************************************************
* @remarks       static void ble_drive_data_para_init(void)
* @brief         BLE参数初始化
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_drive_data_para_init(void)
{
    ble_recv_data_t ble_msg;
    uint8_t i = 0;
    memset ( (uint8_t *)&ble_connect_st, 0x00, sizeof(ble_connect_state_t) );
    memset( (uint8_t *)wifimgr_value, 0x00, WIFIMAR_VALUE_LEN );
    memset( (uint8_t *)wifimgr_ccc_cfg, 0x00, WIFIMAR_CCC_FLAG_LEN );
    memset ( (uint8_t *)&ble_connect_data_counter, 0x00, sizeof(ble_connect_data_counter_t) );
    
    // 清除、释放SOCKET句柄、消息接收队列
    for( i = 0; i < BLE_DATA_QUEUE_DEPTH; i++ )
    {
        if( gaoz_queue_get( ble_recv_data_queue , &ble_msg , 1 ) == 0 )
        {
            gaoz_free_mem((void *)ble_msg.data);
        }
        else
        {
            break;
        }
    }
}
/** ****************************************************************************
* @remarks       static void ble_drive_data_semaphore_create(void)
* @brief         创建BLE数据接收信号量
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_drive_data_semaphore_create(void)
{
    ble_recv_semaphore = gaoz_sem_new(0);
    if( ble_recv_semaphore == 0 )
    {
        while( 1 ); /*创建失败*/
    }
}

/** ****************************************************************************
* @remarks       static uint8_t ble_drive_data_semaphore_get( uint32_t time_out )
* @brief         获取BLE底层接收数据的信号量
* @param[in]     无
* @param[out]    无
* @return        1 接收到数据 ， 0 未接收到数据，超时
* @attention     阻塞状态 
*******************************************************************************/
static uint8_t ble_drive_data_semaphore_get( uint32_t time_out )
{
    if( gaoz_sem_try_wait( ble_recv_semaphore, time_out ) == true ) //等待回应信号量
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/** ****************************************************************************
* @remarks       static uint8_t ble_drive_data_semaphore_set(void)
* @brief         发送 BLE底层接收数据的信号量
* @param[in]     无
* @param[out]    无
* @return       无
* @attention     无
*******************************************************************************/
void ble_drive_data_semaphore_set(void)
{
    system_wakeup_queue_set( SYS_WAKEUP_TRIG_BLE );   
    gaoz_sem_signal( ble_recv_semaphore );              /*发送信号量，通知任务*/
}

/** ****************************************************************************
* @remarks       static void ble_drive_data_queue_create(void)
* @brief         创建发送数据消息队列
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_drive_data_queue_create(void)
{
    /* 创建BLE数据接收消息队列 */
    ble_recv_data_queue = gaoz_queue_create( BLE_DATA_QUEUE_DEPTH, sizeof( ble_recv_data_t ) );
    if( ble_recv_data_queue == 0 )
    {
        while( 1 ); /*创建失败,进行处理*/
    }
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_data_queue_get(net_send_data_s *gprs_msg)
* @brief         获取BLE数据发送消息队列数据
* @param[in]     *ble_msg 获取的数据地址
* @param[in]     time_out 等待数据的时间
* @param[out]    无
* @return        pdPASS 接收到数据 pdFAIL 未接收到数据
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t ble_drive_data_queue_get(ble_recv_data_t *ble_msg ,uint32_t time_out)
{
    if( ble_recv_data_queue == 0 )
    {
        ble_drive_data_queue_create();
    }
    if( gaoz_queue_get( ble_recv_data_queue, ble_msg, time_out )  == 0 ) //等待回应信号量
    {
        return pdPASS;
    }
    else
    {
        return pdFAIL;
    }
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_open( char *ble_name ,ble_drive_state_callback_t statr_cb )
* @brief         打开BLE蓝牙
* @param[in]     *ble_name BLE蓝牙名称 
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
uint32_t ble_drive_data_open( char *ble_name ,ble_drive_state_callback_t statr_cb )
{
    uint8_t name_len = 0;
    uint32_t osR = 0 , res = pdFAIL;
    if( ble_name == NULL )
    {
        return pdFAIL;
    }
    if( ble_send_data_mutex != 0 )
    {   
        gaoz_mutex_lock( ble_send_data_mutex );
        osR = 1;
    }
    memset( (uint8_t *)device_name, 0x00, BLE_DEVICE_NAME_LEN );
    name_len = strnlen( (const char *)ble_name,BLE_DEVICE_NAME_LEN );
    if( name_len != 0 )
    {
        ble_drive_gatt_connect_set( BLE_GATT_OPEN );
        memcpy( (uint8_t *)device_name, ble_name, name_len );
        ble_drive_state_cb = statr_cb;
        res = pdPASS;
    }
    if(osR != 0)
    {
        gaoz_mutex_unlock( ble_send_data_mutex );
    }    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_data_write( uint8_t *data , uint16_t len )
* @brief         写BLE发送数据
* @param[in]     *data 发送数据地址
* @param[in]     len 发送数据的长度
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
uint32_t ble_drive_data_write( uint8_t *data , uint16_t len )
{
    gatt_le_data_info_t notify;
    uint32_t osR = 0 , res = pdFAIL;
    if(( data == NULL ) || ( len == 0 ))
    {
        return pdFAIL;
    }
    if( ble_send_data_mutex != 0 )
    {   
        gaoz_mutex_lock( ble_send_data_mutex );
        osR = 1;
    }
    if( ble_drive_gatt_connect_get() == BLE_GATT_CONNECT ) /*判断BLE连接成功*/
    {
        notify.att_handle = wifi_mgr_chara2.value[2] << 8 | wifi_mgr_chara2.value[1];
        notify.length = len;
        notify.data = (uint8_t *)data;
        notify.acl_handle = ble_drive_acl_handle_get();
        ble_data_printf_data_fun( BLE_DATA_WRITE , data , len );
        if( gaoz_ble_notify( (gatt_le_data_info_t *)&notify,GATT_NOTIFICATION ) >= 0 )
        {
            ble_connect_data_counter.send += len;
            res = pdPASS;
        }
    }
    if(osR != 0)
    {
        gaoz_mutex_unlock( ble_send_data_mutex );
    }    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_data_read( uint8_t *data , uint16_t *len , uint32_t time_out )
* @brief         读取BLE接收到的数据
* @param[out]     *data 接收的数据地址
* @param[out]    *len 接收数据的长度
* @param[out]    time_out 读取数据阻塞的时间 单位ms
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行，可以设置阻塞的时间，将任务挂起；
*******************************************************************************/
uint32_t ble_drive_data_read( uint8_t *data , uint16_t *len , uint32_t time_out )
{
    ble_recv_data_t ble_msg;
    uint32_t res = pdFAIL;
    if(( data == NULL ) || ( len == NULL ))
    {
        return pdFAIL;
    }
    if( ble_drive_gatt_connect_get() == BLE_GATT_CONNECT )
    {
        if( ble_drive_data_queue_get( &ble_msg ,time_out) == pdPASS )
        {
            if(( ble_msg.data != NULL ) && ( ble_msg.len != 0 ))
            {   
                memcpy( ( uint8_t *)data , ( uint8_t *)ble_msg.data ,ble_msg.len );
                *len = ble_msg.len;
                gaoz_free_mem( (void *)ble_msg.data );
                ble_connect_data_counter.recv = ble_msg.len;
                res = pdPASS;
            }
        }
    }
    else
    {
        gaoz_task_sleep( time_out );
    }
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_data_close( void )
* @brief         关闭BLE功能
* @param[in]     
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
uint32_t ble_drive_data_close( char *ble_name )
{
    uint32_t res = pdFAIL;
    if( ble_drive_gatt_connect_get() == BLE_GATT_CONNECT )
    {
        ble_drive_gatt_connect_set( BLE_GATT_CLOSE );
        res = pdPASS;
    }
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t ble_drive_macaddr_read( char *mac_addr )
* @brief         读取BLE MAC物理地址
* @param[in]     无
* @param[out]    mac_addr 目标地址
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t ble_drive_macaddr_read( char *mac_addr )
{
    uint32_t res = pdFAIL;
    if( mac_addr == NULL )
    {
        return res;
    }
    if(  gaoz_ble_set_read_addr( 1 , 0 , mac_addr ) == 0 )
    {
        res = pdPASS;
    }
    return res;
}

/** ****************************************************************************
* @remarks       void ble_drive_connect_state_set(uint16_t acl, uint16_t st)
* @brief         设置BLE底层返回的连接状态
* @param[in]     acl acl_handle
* @param[in]     st 0 网络断开 1 网络连接成功 
* @param[out]    无
* @return       无
* @attention     无
*******************************************************************************/
void ble_drive_connect_state_set(uint16_t acl, uint16_t st)
{
    ble_connect_st.st = st;
    ble_connect_st.acl = acl;
}

/** ****************************************************************************
* @remarks       static uint16_t ble_drive_connect_state_get( void )
* @brief         获取BLE网络连接的状态
* @param[in]     无
* @param[out]    无
* @return        返回网络连接的状态 0 无连接 1 已连接
* @attention     无
*******************************************************************************/
static uint16_t ble_drive_connect_state_get( void )
{
   return ble_connect_st.st;
}

/** ****************************************************************************
* @remarks       static uint16_t ble_drive_acl_handle_get( void )
* @brief         获取BLE ACL_HANDLE 数据
* @param[in]     无
* @param[out]    无
* @return        返回ACL_HANDLE
* @attention     无
*******************************************************************************/
static uint16_t ble_drive_acl_handle_get( void )
{
   return ble_connect_st.acl;
}

/** ****************************************************************************
* @remarks       void ble_drive_gatt_connect_set( ble_gatt_connect_e st )
* @brief         设置BLE gatt 的连接状态
* @param[in]     无
* @param[out]    无
* @return        返回gatt_connect 状态
* @attention     无
*******************************************************************************/
void ble_drive_gatt_connect_set( ble_gatt_connect_e st )
{
    ble_gatt_connect_st = st;
}

/** ****************************************************************************
* @remarks       static ble_gatt_connect_e ble_drive_gatt_connect_get( void )
* @brief         获取BLE gatt 的连接状态
* @param[in]     无
* @param[out]    无
* @return        返回gatt_connect 状态
* @attention     无
*******************************************************************************/
ble_gatt_connect_e ble_drive_gatt_connect_get( void )
{
    return ble_gatt_connect_st;
}

/** ****************************************************************************
* @remarks       uint32_t ble_send_data_total_count_get( void )
* @brief         获取BLE 发送的数据总量
* @param[in]     无
* @param[out]    无
* @return        发送数据总量
* @attention     无
*******************************************************************************/
uint32_t ble_send_data_total_count_get( void )
{
    return ble_connect_data_counter.send;
}

/** ****************************************************************************
* @remarks       uint32_t ble_recv_data_total_count_get( void )
* @brief         获取BLE 接收的数据总量
* @param[in]     无
* @param[out]    无
* @return        接收数据总量
* @attention     无
*******************************************************************************/
uint32_t ble_recv_data_total_count_get( void )
{
    return ble_connect_data_counter.recv;
}

/** ****************************************************************************
* @remarks       static void ble_data_printf_data_fun( ble_data_mode_e mode , uint8_t *p_data , uint16_t d_len )
* @brief         打印BLE 数据
* @param[in]     mode 打印模式 BLE_DATA_WRITE 写数据  BLE_DATA_READ 读数据
* @param[in]     *p_data 数据的目标地址
* @param[in]     d_len 网络节点
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_data_printf_data_fun( ble_data_mode_e mode , uint8_t *p_data , uint16_t d_len )
{   
    uint8_t *pBuf = NULL ;
    uint16_t data_len = 0;
    
    if(( p_data == NULL ) || ( d_len > BLE_DATA_MAX_LEN ))
    {
        return;
    }
    /*动态申请空间，由于接收的数据需要转变为STRING类型，数据量是原始数据的2倍*/
    pBuf = gaoz_malloc_mem( d_len * 2  + 50 );
    if( pBuf != NULL )
    {   
        if( mode == BLE_DATA_WRITE )
        {
            data_len = sprintf((char *)pBuf,"BLE management writer data:%d,",d_len );
        }
        else// if( mode == BLE_DATA_READ )
        {
            data_len = sprintf((char *)pBuf,"BLE management read data:%d,",d_len );
        }
        data_len += HexToAsciiString((char *)&pBuf[data_len],( const char * )p_data, d_len);
        pBuf[ data_len ] = '\r';
        data_len++;
        pBuf[ data_len ] = '\n';
        data_len++;
        /*发送数据*/
        log_debug_send( DEBUG_MODE,BLE_MAN_NAME ,pBuf,data_len );
        gaoz_free_mem( (void *)pBuf );
    }
}

/** ****************************************************************************
* @remarks       static uint32_t ble_drive_task_state_cb( void * state )
* @brief         BEL状态 ，回调函数
* @param[in]     *state 发送的数据不定类型
* @param[out]    无
* @return        pdPASS 发送数据成功  pdFAIL 发送数据失败
* @attention     无
*******************************************************************************/
static uint32_t ble_drive_task_state_cb( uint8_t state )
{
	if( ble_drive_state_cb == NULL )
    {
		return pdFAIL;
    }
	ble_drive_state_cb( state );
	return pdPASS;
}

/** ****************************************************************************
* @remarks       void ble_create_task( unsigned portBASE_TYPE uxPriority )
* @brief         创建BLE基础数据处理任务
* @param[in]     uxPriority 优先级
* @param[out]    无
* @return        无
* @attention     在系统启动后进行创建
*******************************************************************************/
void ble_create_task( unsigned portBASE_TYPE uxPriority )
{
    ble_drive_state_cb = NULL;
    ble_gatt_connect_st = BLE_GATT_INIT;
    ble_power_st = BLE_POWER_CLOSE;
    ble_drive_data_semaphore_create();
    ble_drive_data_queue_create();
    /*创建任务互斥体*/
    ble_send_data_mutex = gaoz_mutex_create();
    if( ble_send_data_mutex == 0 )
    {
        while(1); /*创建失败*/
    }
    ble_recv_data_mutex  = gaoz_mutex_create();
    if( ble_recv_data_mutex == 0 )
    {
        while(1); /*创建失败*/
    }
    gaoz_thread_create( ble_data_handle_task, BLE_MAN_NAME, 1024*8, NULL, uxPriority );
}

/** ****************************************************************************
* @remarks       static uint32_t ble_task_into_run_mode(void)
* @brief         BLE任务进入运行状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t ble_task_into_run_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL;
    state = power_man_save_state_get( ble_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_RUN_MODE )
    {   
        if( ble_power_st == BLE_POWER_OPEN )
        {
            //gaoz_ble_enable_dev( 0 );                             /* 关闭BLE广播模式*/
            //ble_drive_cfg_broadcast_time( 1000 );              
            //gaoz_ble_enable_dev( 1 );                             /* 关闭BLE广播模式*/
        }
        power_man_save_state_set( ble_power_man_id ,TASK_RUN_MODE );
        log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"<<<<<<<<<<*****BLE task enters RUN mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_RUN_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}
/** ****************************************************************************
* @remarks       static uint32_t ble_task_into_sleep_mode(void)
* @brief         BLE任务进入睡眠状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t ble_task_into_sleep_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( ble_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_SLEEP_MODE )
    {   
        if( ble_power_st == BLE_POWER_OPEN )
        {
            //gaoz_ble_enable_dev( 0 );                             /* 关闭BLE广播模式*/
            ////ble_drive_cfg_broadcast_time( 3000 );              
            //gaoz_ble_enable_dev( 1 );                             /* 关闭BLE广播模式*/
        } 
        power_man_save_state_set( ble_power_man_id ,TASK_SLEEP_MODE );
        log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"<<<<<<<<<<*****BLE task enters SLEEP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_SLEEP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}
/** ****************************************************************************
* @remarks       static uint32_t ble_task_into_stop_mode(void)
* @brief         BLE任务进入停止状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t ble_task_into_stop_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( ble_power_man_id );   /*获取任务的运行状态*/
    if( state != TASK_STOP_MODE )
    {   
        gaoz_ble_enable_dev( 0 );                               /* 关闭BLE广播模式*/
        gaoz_bt_onoff( 0 );                                     /* 关闭蓝牙功能*/
        ble_drive_gatt_connect_set( BLE_GATT_INIT );
        power_man_save_state_set( ble_power_man_id ,TASK_STOP_MODE );
        log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"<<<<<<<<<<*****BLE task enters STOP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_STOP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}

/** ****************************************************************************
* @remarks       static uint32_t ble_task_open_drive(void)
* @brief         BLE打开
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t ble_task_open_drive(void)
{
    #define BLE_MAC_ADDR_MAX_LEN  32 
	uint32_t config_size = 0 , ret = pdFAIL;
    char ble_mac_addr[BLE_MAC_ADDR_MAX_LEN] = { 0 }, ble_mac_data[BLE_MAC_ADDR_MAX_LEN] = { 0 };
    uint8_t ble_mac_len = 0, i = 0, j = 0;
    
    fibo_taskSleep( 3000 );                                                 /* 打开蓝牙功能后等待5S */
    log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service start configuration\r\n",0);
    ble_drive_data_para_init();                                             /*初始系统参数*/
    gaoz_bt_onoff( 1 );                                                     /* 打开蓝牙功能*/
    fibo_taskSleep(2000);                                                   /* 打开蓝牙功能后等待2S */
    gaoz_ble_set_read_name(0,(uint8_t *)device_name,0);
    config_size = sizeof(config_wifi_service)/sizeof(gatt_element_t);
    if( gaoz_ble_add_service_and_characteristic(config_wifi_service,config_size) < 0 ) 
    {
        ble_drive_gatt_connect_set( BLE_GATT_ERROR );                       /* BLE初始化异常*/
        log_debug_printf(ERROR_MODE,BLE_MAN_NAME ,"[%s]BLE service configuration failed\r\n",sys_err_infor_pointer_get( 17 ));
    }
    else
    {
        log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service configuration successful\r\n",0);
        ble_drive_cfg_broadcast_time( 1000 );
        if( ble_drive_macaddr_read( ble_mac_addr ) == pdPASS )
        {
            ble_mac_len = strlen( (const char *)ble_mac_addr );
            log_debug_printf(INFOR_MODE,BLE_MAN_NAME ,"BLE service read mac address : len = %d,data= %s\r\n",ble_mac_len, ble_mac_addr );
            for( i = 0; i < ble_mac_len ; i++ )
            {
                if( ble_mac_addr[i] != ':' )
                {
                    ble_mac_data[j] = ble_mac_addr[i];
                    j += 1;
                }
            }
            if( j > 0 )
            {
                memset(( uint8_t *)ble_mac_addr, 0x00, BLE_MAC_ADDR_MAX_LEN );
                for( i = 0; i < j/2 ; i++ )
                {
                    ble_mac_addr[i*2] = ble_mac_data[j - ( i + 1 )*2]; 
                    ble_mac_addr[i*2+1] = ble_mac_data[j - ( i + 1 )*2 + 1];
                }
                memset(( uint8_t *)ble_mac_data, 0x00, BLE_MAC_ADDR_MAX_LEN );
                ble_mac_len = sprintf( ble_mac_data, "%02xFF484D%s" , j / 2 + 3, ble_mac_addr );
                log_debug_printf(INFOR_MODE,BLE_MAN_NAME ,"BLE service broadcast : len = %d,data = %s\r\n",ble_mac_len /2,  ble_mac_data);
                gaoz_ble_set_dev_data( ble_mac_len / 2, ble_mac_data );
            }
        }
        fibo_taskSleep(1000);                                                /* 打开蓝牙功能后等待2S */
        gaoz_ble_enable_dev( 1 );                                            /* 打开BLE广播模式*/
        ble_drive_gatt_connect_set( BLE_GATT_BROAD_OK );                     /*蓝牙模块打开广播模式*/
        ret = pdPASS;
    }
    return ret;
}

/** ****************************************************************************
* @remarks       static void ble_task_data_processing( uint32_t time_out )
* @brief         BLE数据处理
* @param[in]     time_out 阻塞时间
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_task_data_processing( uint32_t time_out )
{   
    if( ble_drive_data_semaphore_get( time_out ) == 1 )
    {   
        if( ble_drive_acl_handle_get() == 0 )
        {   
            if( ble_drive_connect_state_get() == 0 )  
            {
                log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service disconnected client successfully\r\n",0);
                gaoz_ble_enable_dev( 1 );
                fibo_taskSleep(1000);
                ble_drive_gatt_connect_set( BLE_GATT_BROAD_OK );
            }
            else if( ble_drive_connect_state_get() == 1 )
            {
                ble_drive_gatt_connect_set( BLE_GATT_CONNECT );
                log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service connected to client successfully\r\n",0 );
            }
        }
    }
    else
    {
        if( ble_drive_gatt_connect_get() == BLE_GATT_OPEN )
        {
            if( ble_power_st == BLE_POWER_OPEN )
            {
                gaoz_ble_enable_dev( 0 );                    /* 关闭BLE广播模式*/
                gaoz_bt_onoff( 0 );                          /* 关闭蓝牙功能*/
                log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service close,broadcast close\r\n",0);
            }
            ble_drive_gatt_connect_set( BLE_GATT_INIT );
            if( ble_task_open_drive() == pdPASS )            /*  打开BLE蓝牙*/
            {
                ble_power_st = BLE_POWER_OPEN;
            }
        }
        else if( ble_drive_gatt_connect_get() == BLE_GATT_CLOSE ) 
        {   
            gaoz_ble_enable_dev( 0 );                        /* 关闭BLE广播模式*/
            gaoz_bt_onoff( 0 );                              /* 关闭蓝牙功能*/
            log_debug_send(INFOR_MODE,BLE_MAN_NAME ,"BLE service close,broadcast close\r\n",0);
            ble_drive_gatt_connect_set( BLE_GATT_INIT );
            ble_power_st = BLE_POWER_CLOSE;
        }
    }
}

/** ****************************************************************************
* @remarks       static void ble_drive_cfg_broadcast_time( uint32_t time_ms )
* @brief         配置BLE广播时间
* @param[in]     broadcast_time BLE广播时间，单位mS；
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_drive_cfg_broadcast_time( uint32_t time_ms )
{   
    uint32_t adv_time = 0;
    adv_time = time_ms * 0.625;
    fibo_ble_set_dev_param( 6,adv_time, adv_time, 0, 0, -1, 7, 0, NULL );
}

/** ****************************************************************************
* @remarks       static void ble_data_handle_task( void * pvParameters )
* @brief         BLE基础数据处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void ble_data_handle_task( void * pvParameters )
{
    ( void ) pvParameters; 
    task_modules_e ble_run_st;
    volatile uint32_t ble_broad_sleep_time = 0;
    mon_reg_task_dog( 60 * GAOZ_TICK_PERIOD_S ,(uint8_t *)BLE_MAN_NAME , TASK_SEM_YES );           /*注册任务看门狗*/
    power_man_task_reg((uint8_t * )BLE_MAN_NAME,(uint8_t *)&ble_power_man_id ); /*注册系统电源管理*/
    log_debug_send(DEBUG_MODE,BLE_MAN_NAME ,"BLE management task started successfully\r\n",0);
    //ble_drive_data_open( "L610_BLE123",NULL );
    for(;;)
    {
        mon_reset_task_dog();
        ble_run_st = power_man_task_state_get( ble_power_man_id );          /*获取任务运行的状态*/
        /*******************************BLE任务处于运行状态***********************************/
        if(  ble_run_st == TASK_RUN_MODE )                                  /*任务进入全速运行模式*/
        {
            if( ble_task_into_run_mode() != pdPASS )                        /*判断睡眠是否设置成功，没有设置成功进入延时*/
            {
                gaoz_task_sleep(1000);
                continue;
            }
            ble_broad_sleep_time = 0;
            ble_drive_task_state_cb(TASK_RUN_MODE);
            ble_task_data_processing( BLE_DATA_SAM_REV_RUN_WAIT_TIME );
        }
        /*******************************BLE任务处于休眠状态************************************/
        else if( ble_run_st == TASK_SLEEP_MODE ) 
        {
            ble_task_data_processing( BLE_DATA_SAM_REV_SLEEP_WAIT_TIME );
            if( ble_drive_gatt_connect_get() !=   BLE_GATT_CONNECT )           /*判断蓝牙模式是否处于链接*/
            {
                ble_broad_sleep_time ++;
                if( ble_broad_sleep_time >= POWER_MAN_TASK_INTO_SLEPP_TIME )
                {
                    ble_broad_sleep_time = POWER_MAN_TASK_INTO_SLEPP_TIME;
                    ble_drive_task_state_cb(TASK_SLEEP_MODE);
                    ble_task_into_sleep_mode();                               /*判断任务任务是否进入睡眠模式，进入睡眠模式后进行长时间延时*/ 
                }
            }
        }
        /*******************************BLE任务处于停止状态************************************/
        else if(  ble_run_st == TASK_STOP_MODE )
        {
            if( ble_task_into_stop_mode() == pdPASS )                         /*判断任务任务是否进入停止模式，进入停止模式后进行长时间延时*/ 
            {   
                gaoz_task_sleep( 1000 );
                continue;
            }
            gaoz_task_sleep(1000);
        }
        /*******************************BLE任务空循环状态************************************/
        else
        {
            gaoz_task_sleep(100);
        }
    }
}

